#include "link/include/factory.h"
int enroll(MYSQL* conn,pnode_t pnod)
{
    printf("enroll\n");
    int i,j,k,l;
    int len;
    int rec;//用于给客户端发记号
    char lbuf[128]={0};
    char salt[SALT_LEN+1]={0};
    char encrypted[36]={0};
    char pass[23]={0};
    //train_t dt;
    unsigned int num;
    MYSQL_RES *res;
    MYSQL_ROW row;
    char query[256]={0};
    while(1)
    {
        printf("接受yongmumign\n");
        //接收用户名
        if(!recv(pnod->newfd,&len,4,0)){return -1;}
        printf("len%d\n",len);
        if(!recv(pnod->newfd,pnod->username,len,0)){return -1;}
        printf("pnbouserw%s\n",pnod->username);
        sprintf(query,"select id from admin where username='%s'",pnod->username);
        puts(query);
        sql_query(conn,&res,query,&num);
        puts(query);
        if(res)
        {
            if((row=mysql_fetch_row(res))!=NULL)
            {
                rec=1;
            }else{//0表示用户名不重复
                rec=0;
            }
            send(pnod->newfd,&rec,4,0);
	    //Must free result set immediately before next query executed, otherwise error will happened.
            mysql_free_result(res);//释放结果集合
            if(0==rec)break;
        }
    }
    printf("接受密文\n");
    //接收密文
    if(!recv(pnod->newfd,&len,4,0)){return -1;}
    if(!recv(pnod->newfd,encrypted,len,0)){return -1;}
    for(i=j=k=l=0;j<(int)strlen(encrypted)-1;++j)
    {
        if('$'==*(encrypted+j))++i;//记录$出现的次数
        if(2==i&&k<SALT_LEN)salt[k++]=*(encrypted+j+1);
        if(3==i)pass[l++]=*(encrypted+j+1);
    }
    printf("i=%dsalt:%s|pass:%s|\n",i,salt,pass);
    sprintf(query,"insert into admin (username,salt,passwd) values('%s','%s','%s')",pnod->username,salt,pass);
    printf("query:%s\n",query);
    sql_insert(conn,query);//登记用户信息
    bzero(query,sizeof(query));
    sprintf(query,"insert into repository (precode,owner,filename,size,md5sum) values (0,'%s','%s',-1,'0')",pnod->username,pnod->username);
    printf("query:%s\n",query);
    sql_insert(conn,query);//创建用户的根目录
    wrlog(conn,-1,lbuf,pnod);
    login(conn,pnod);
    return 0;
}
int login(MYSQL* conn,pnode_t pnod)
{
    printf("login:conn:%p\n",conn);
    printf("login\n");
    char lbuf[128]={0};
    train_t dt;
    dt.datalen=4;
    int rec;
    int len;
    char passwd[128]={0};
    char encrypted[64]={0};
    int i,j;//用于剥离多余数据
    char query[256]={0};
    MYSQL_RES *res;
    MYSQL_ROW row;
    unsigned int num;
    while(1)
    {//接收用户名
        bzero(encrypted,sizeof(encrypted));
        if(!recv(pnod->newfd,&len,4,0)){return -1;}
        printf("len=%d\n",len);
        if(!recv(pnod->newfd,pnod->username,len,0)){return -1;}
        puts(pnod->username);
        sprintf(query,"select salt from admin where username='%s'",pnod->username);
        puts(query);
        sql_query(conn,&res,query,&num);
        puts(query);
        if(res)
        {
            if((row=mysql_fetch_row(res))!=NULL)
            {
                printf("%s|\n",row[num]);
                dt.datalen=strlen(row[num]);
                strcpy(dt.buf,row[num]);
                send(pnod->newfd,&dt,4+dt.datalen,0);//发送对应盐值
                mysql_free_result(res); //释放结果集合
            }else{//发送长度为零的字符串表示没有该用户
                dt.datalen=0;
                send(pnod->newfd,&dt,4+dt.datalen,0);
                bzero(pnod->username,sizeof(pnod->username));
                mysql_free_result(res); //释放结果集合
                continue;
            }
        }
        //接收密文
        if(!recv(pnod->newfd,&len,4,0)){return -1;}
        if(!recv(pnod->newfd,passwd,len,0)){return -1;}
        bzero(query,strlen(query));
        sprintf(query,"select passwd from admin where username='%s'",pnod->username);
        puts(query);
        sql_query(conn,&res,query,&num);
        if(res)
        {
            if((row=mysql_fetch_row(res))!=NULL)
            {
                printf("%s|\n",row[num]);
                for(i=0,j=12;*(passwd)!='\0';++i,++j)
                {
                    *(encrypted+i)=*(passwd+j);
                }
                printf("encrypoetd:%s|\n",encrypted);
                if(0==strcmp(encrypted,row[num]))
                {//登陆成功，并设置当前用户的根目录
                    rec=0;
                    memcpy(dt.buf,&rec,4);
                    send(pnod->newfd,&dt,4+dt.datalen,0);
                    mysql_free_result(res);
                    bzero(query,sizeof(query));
                    sprintf(query,"select code from repository where precode=0 and owner='%s'",pnod->username);
                    puts(query);
                    sql_query(conn,&res,query,&num);
                    if(res)
                    {//获取用户的根目录
                        row=mysql_fetch_row(res);
                        pnod->pathcode[0]=atoi(row[0]);
                        printf("pnod->pthcode[0]%d\n",pnod->pathcode[0]);
                    }
                    mysql_free_result(res);
                    pnod->level=0;
                    wrlog(conn,0,lbuf,pnod);
                    break;
                }else{
                    bzero(encrypted,sizeof(encrypted));
                    rec=1;//密码错误
                    memcpy(dt.buf,&rec,4);
                    send(pnod->newfd,&dt,4+dt.datalen,0);
                    mysql_free_result(res);
                }
            }else{
                return -1;
            }
    //        mysql_free_result(res);
        }
    }
    return 0;
}
int wrlog(MYSQL *conn,int opt,char *buf,pnode_t pnod)
{
    time_t now=time(NULL);
    char lbuf[256]={0};//logbuffer
    strcpy(lbuf,pnod->username);
    strcat(lbuf,": ");
    switch(opt){
    case -2:
        strcat(lbuf,"logout");
        break;
    case -1:
        strcat(lbuf,"register");
        break;
    case 0:
        strcat(lbuf,"login");
        break;
    case 1:
        strcat(lbuf,"cd ");
        break;
    case 2:
        strcat(lbuf,"ls");
        break;
    case 3:
        strcat(lbuf,"puts ");
        break;
    case 4:
        strcat(lbuf,"gets ");
        break;
    case 5:
        strcat(lbuf,"remove ");
        break;
    case 6:
        strcat(lbuf,"pwd");
        break;
    case 7:
        strcat(lbuf,"mkdir ");
        break;
    default:
        return -1;
    }
    strcat(lbuf,buf);
    strcat(lbuf," @ ");
    strcat(lbuf,ctime(&now));
    char query[256]={0};
    sprintf(query,"insert into log (log) values ('%s');",lbuf);
    puts(query);
    sql_insert(conn,query);
    size_t len=strlen(lbuf);
    int fd=open("link/log/log",O_WRONLY|O_APPEND);
    write(fd,lbuf,len);
    return 0;
}
int trans_file(int newfd,int fd)
{
    off_t sended=0;//记录已发送字节数
    signal(SIGPIPE,SIG_IGN);
    train_t dt;//dataTrain
    bzero(&dt,sizeof(train_t));
    //接收对端已经存在的文件的大小
    recv(newfd,&sended,sizeof(off_t),0);
    //发送文件大小
    struct stat buf;
    fstat(fd,&buf);
    dt.datalen=sizeof(buf.st_size);
    memcpy(dt.buf,&buf.st_size,dt.datalen);
    send(newfd,&dt,sizeof(dt.datalen)+dt.datalen,0);
    //发送文件
    while((dt.datalen=pread(fd,dt.buf,sizeof(dt.buf),sended)))
    {
        send(newfd,&dt,sizeof(dt.datalen)+dt.datalen,0);
        sended+=dt.datalen;
    }
    //判断传输是否成功
    if(sended<buf.st_size)
    {
        return -1;
    }
    dt.datalen=0;
    send(newfd,&dt,4,0);
    return -1;
}
int recv_file(int newfd,char *md5,pnode_t pnod,off_t fsize)
{
    int ret;
    //接收文件    
    char buf[512]={0};
    strcpy(buf,pnod->homepath);
    strcat(buf,"/");
    strcat(buf,md5);
    int fd;    
    //创建文件    
    puts(buf);
    fd=open(buf,O_RDWR|O_CREAT|O_EXCL,0666);//若文件已存在，则返回-1
    ERROR_CHECK(fd,-1,"open");//用root账户登录时，把仓库地址设为~/netdisc/server/home/，会提示文件不存在，暂时不知道为什么，暂时先写绝对路径，可以解决这个问题
    //fd=creat(buf,0666);
    ftruncate(fd,fsize);//做出对应大小的文件    
    char *pstart=(char*)mmap(NULL,fsize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);    
    ERROR_CHECK(pstart,(char*)-1,"mmap");    
    ret=recvcycle(newfd,pstart,fsize);    
    if(0==ret)    
    {        
        munmap(pstart,fsize);        
    }else if(-1==ret){//传输中断，删除未传输完成的文件
        munmap(pstart,fsize);        
        unlink(buf);
	return -1;
    }
    return 0;
}
int recvcycle(int sockfd,void *pstart,int len)
{
    char *p=(char*)pstart;
    int total=0,ret;
    while(total<len)
    {
        ret=recv(sockfd,p+total,len-total,0);
        if(0==ret)//对端断开
        {
            printf("Something wrong happened!\n");
            return -1;
        }
        total+=ret;
    }
    return 0;
}
